

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;

public class Ant implements defAnt {

	//Fields
	private static final int NOFOOD = 20;
	private static final int GOTFOOD = 40;
	public static enum DIRECTION { leftBottomLeft, left, rightTopRight, right, leftTopTop, top, rightBottomBottom, bottom, leftTopLeft, leftTop, leftBottomBottom, leftBottom, rightTopTop, rightTop, rightBottomRight, rightBottom };//Reihenfolge wichtig!!!!
	public static final DIRECTION [] defaultPrefDir = { DIRECTION.leftBottomLeft, DIRECTION.left, DIRECTION.rightTopRight, DIRECTION.right, DIRECTION.leftTopTop, DIRECTION.top, DIRECTION.rightBottomBottom, DIRECTION.bottom, DIRECTION.leftTopLeft, DIRECTION.leftTop, DIRECTION.leftBottomBottom, DIRECTION.leftBottom, DIRECTION.rightTopTop, DIRECTION.rightTop, DIRECTION.rightBottomRight, DIRECTION.rightBottom };
	private static final int [] dirActions = { 13, 12, 31, 32, 11, 21, 33, 23, 12, 11, 23, 13, 21, 31, 32, 33 };
	// 1.Stelle: x-Coordinate, 1->-1, 2->0, 3->1;
	// 2.Stelle: y-Coordinate, 1->-1, 2->0, 3->1.
		
	private static Random rand = new Random();
	
	//Attributes
	private Point position;
	private PTrail pTrail;
	public int food = NOFOOD;
	private DIRECTION [] prefDir;
	private boolean secondDirectionChosen = false;
	private DIRECTION beforeLastDir;
	
	private AntSimulation antSim;
	
	//Constructor
	public Ant( Point p ,AntSimulation as){
		antSim=as;
		
		position = new Point( p );
		prefDir = defaultPrefDir.clone();
		antSim.getForestground()[p.x][p.y] *= -1;
	}
	
	
	public Ant( Point p, DIRECTION dir ,AntSimulation as){
		antSim=as;
		
		position = new Point( p );
		prefDir = defaultPrefDir.clone();
		for(int i=0; i<16; i++){
			changeOrder(defaultPrefDir[rand.nextInt(defaultPrefDir.length)]);
		}
		changeOrder( dir );
		antSim.getForestground()[p.x][p.y] *= -1;
		pTrail = new PheromoneTrail(antSim);
		beforeLastDir = prefDir[15];
	}
	
	
	/*
	Methods
	*/
	
	//getter - Methods
	
	public int getX(){
		return this.position.x;
	}
	
	public int getY(){
		return this.position.y;
	}
	
	public int getFood(){
		return this.food;
	}
	
	public PTrail getPtrail(){
		return (PheromoneTrail) this.pTrail;
	}
	

	
	
	// other Methods

	private void changeOrder( DIRECTION dir ){
		DIRECTION saveDir = dir, tmpDir = prefDir[0];
		int i = 0;
		while( prefDir[i] != dir ){
			tmpDir = prefDir[i];
			prefDir[i] = saveDir;
			saveDir = tmpDir;
			i++;
		}
		prefDir[i] = tmpDir;
	}
	
	
	private boolean stepDirection( Point nextPoint ){
		
		for( int i = 0; i < prefDir.length; i++ ){
			DIRECTION secDir = prefDir[1];
			if( i > 1 )
				secondDirectionChosen = false;
			DIRECTION actDir = prefDir[i];
			int action = Ant.dirActions[ actDir.ordinal() ];
			if( actDir.ordinal()%2 == 0 ){
				secondDirectionChosen = true;
				secDir = Ant.defaultPrefDir[ actDir.ordinal() + 1 ];
			}
			int aktx = nextPoint.x + action%10 - 2;//xdiff;
			action/=10;
			int akty = nextPoint.y + action - 2;//ydiff;
			if( i > 0 && actDir == beforeLastDir )
				continue;
			if( aktx >= 0 && aktx < antSim.getSimWidth() && akty >= 0 
					&& akty < antSim.getSimHeight() 
					&& antSim.getForestground()[aktx][akty] > 0 ){
				nextPoint.x = aktx;
				nextPoint.y = akty;
				if( i > 0 )
					beforeLastDir = prefDir[0];
				changeOrder( prefDir[i] );
				if( secondDirectionChosen ){
					changeOrder( secDir );
				}
				return true;
			}
			if( aktx > 0 && aktx < antSim.getSimWidth() 
					& akty > 0 && akty < antSim.getSimHeight() 
					&& antSim.getForestground()[aktx][akty] < -255 && this.food == NOFOOD ){
				this.food = GOTFOOD;
				antSim.getForestground()[aktx][akty] += GOTFOOD;
				if( antSim.getForestground()[aktx][akty] >= -255 )
					antSim.getForestground()[aktx][akty] = 1;
				return false;
			}
			if(antSim.anthill_rectangle.isAtBorder(aktx, akty) )
				this.food = NOFOOD;
		}
		return false;
	}

	
	private void validatePheromoneTrail(){
		pTrail.validate( position, this.food );
	}
	
	
	public void draw( Graphics g ){
		Color tmp;
		if( food == GOTFOOD )
			tmp = Color.red;
		else
			tmp = Color.black;
//		g.setColor(tmp);
//		g.fillRect( position.x, position.y, 1, 1);
		antSim.setUnderlayerColor(position.x, position.y, tmp.getRGB());
	}

	
	public void drawTrail( Graphics g ){
		pTrail.draw( g );
	}
	
	
	public void stepForward(){
		Point nextPoint = new Point( position );
		if( this.stepDirection( nextPoint ) ){
			antSim.getForestground()[position.x][position.y] *= -1;
			antSim.getForestground()[nextPoint.x][nextPoint.y] *= -1;
			position = nextPoint;
			validatePheromoneTrail();
		}
	}


	
	
}
